<?php
/**
 * Description: 阿里云开放搜索服务
 * User: devforma
 * Date: 16/9/6
 * Time: 13:52
 */

class AliyunOpenSearch {

    const BASEURL = 'http://opensearch-cn-hangzhou.aliyuncs.com/search?';
    const DATA_QUESTIONS = 'questions';
    const AccessKeySecret = ALIYUN_ACCESSKKEYSECRET;


    private $appName;
    private $config = "config=start:0,hit:10,format:json";
    private $query = 'query=';
    private $filter = '';


    /**
     * 指定数据源
     *
     * @param $appName
     * @return $this
     */
    public function from ($appName) {
        $this->appName = $appName;

        return $this;
    }

    /**
     * 开始构造查询
     *
     * @param string $key 待查询的列
     * @param string $keyword 关键词
     * @return $this
     */
    public function search ($key, $keyword) {
        $this->query .= $key . ":'$keyword'";

        return $this;
    }

    /**
     * 构造查询中的and结构
     *
     * @param string $key 待查询的列
     * @param string $keyword 关键词
     * @return $this
     */
    public function searchAnd ($key, $keyword) {
        $this->query .= " AND {$key}:'{$keyword}'";

        return $this;
    }

    /**
     * 构造查询中的or结构
     *
     * @param string $key 待查询的列
     * @param string $keyword 关键词
     * @return $this
     */
    public function searchOr ($key, $keyword) {
        $this->query .= " OR {$key}:'{$keyword}'";

        return $this;
    }

    /**
     * 构造查询中的过滤条件
     *
     * @param string $key 过滤字段
     * @param string $value 限定值
     * @return $this
     */
    public function filter($key, $value) {
        if (empty($this->filter))
            $this->filter = "&&filter={$key}={$value}";
        else
            $this->filter .= " AND {$key}={$value}";

        return $this;
    }


    /**
     * 分页
     *
     * @param int $offset 起始位置
     * @param int $count 数量
     * @return $this
     */
    public function limit ($offset, $count) {
        if ($offset + $count > 5000) //这里有参数使用的限制
            return $this;

        $this->config = "config=start:{$offset},hit:{$count},format:json";

        return $this;
    }

    /**
     * 执行查询
     *
     * @return object
     */
    public function exec() {
        $params = [
            'Version'          => 'v2',
            'AccessKeyId'      => '5KrQDLJXdE9SXB2r',
            'SignatureMethod'  => 'HMAC-SHA1',
            'Timestamp'        => gmdate('Y-m-d\TH:i:s\Z'),
            'SignatureVersion' => '1.0',
            'SignatureNonce'   => microtime(true),
            'index_name'       => $this->appName,
            'query'            => $this->config . '&&' . $this->query . $this->filter
        ];

        $url = self::BASEURL . self::getSignedQuery($params);

        if (($result = self::httpGet($url)) && $result->status == 'OK') {
            return $result->result;
        }

        return null;
    }

    /**
     * 获取签名后的请求字符串
     *
     * @param array $params 参数数组
     * @return string
     */
    private static function getSignedQuery($params) {

        ksort($params);
        $query = str_replace('+', '%20', http_build_query($params));

        $str = 'GET&%2F&' . urlencode($query);

        return $query . '&Signature=' . urlencode(base64_encode(hash_hmac('sha1', $str, self::AccessKeySecret . '&', true)));
    }


    /**
     * 获取查询结果
     *
     * @param string $url 地址
     * @return object
     */
    private static function httpGet($url) {
        $ch = curl_init($url);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $data = curl_exec($ch);

        return !empty($data) ? json_decode($data) : null;
    }
}